package sqlToGUI.charts;

import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Image;
import java.awt.Point;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import org.jfree.chart.JFreeChart;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.plot.dial.DialBackground;
import org.jfree.chart.plot.dial.DialCap;
import org.jfree.chart.plot.dial.DialPlot;
import org.jfree.chart.plot.dial.DialPointer;
import org.jfree.chart.plot.dial.DialTextAnnotation;
import org.jfree.chart.plot.dial.DialValueIndicator;
import org.jfree.chart.plot.dial.StandardDialFrame;
import org.jfree.chart.plot.dial.StandardDialRange;
import org.jfree.chart.plot.dial.StandardDialScale;
import org.jfree.data.general.DefaultValueDataset;
import org.jfree.ui.GradientPaintTransformType;
import org.jfree.ui.StandardGradientPaintTransformer;

import sqlToGUI.charts.helperUtilities.TelemetryChartEvent;
import sqlToGUI.charts.helperUtilities.TelemetryChartListener;
import sqlToGUI.charts.helperUtilities.TelemetryDataEntry;


public class SpeedChart implements GUIDisplay {
	
	/**The list receiving the new data from the outside -
	 * This class will be responsible for listening to this
	 * list and updating from it whenever new information
	 * is available -
	 * The array is used in case chart uses reference to more
	 * than one data set and is updated from more than one
	 * list */
	private TelemetryDataEntry [] dataEntries;
	
	/**The log panel data will monitor the incoming data */
	private LogPanel log;
	/**Variable indicating whether or not a log has been
	 * registered */
	private boolean logReg = false;
	
	private DefaultValueDataset[] buffer;

	private JFreeChart chart;
	private ChartPanel panel;

	public SpeedChart() {
		buffer = new DefaultValueDataset[2];
		buffer[0] = new DefaultValueDataset(50);
		buffer[1] = new DefaultValueDataset(70);

		DialPlot plot = new DialPlot();
		plot.setDataset(0, buffer[0]);
		plot.setDataset(1, buffer[1]);
        StandardDialFrame dialFrame = new StandardDialFrame();
		dialFrame.setBackgroundPaint(Color.lightGray);
        dialFrame.setForegroundPaint(Color.darkGray);
        plot.setDialFrame(dialFrame);
		GradientPaint gp = new GradientPaint(new Point(), new Color(255, 255, 255), new Point(), new Color(0,90, 0));
		DialBackground db = new DialBackground(gp);
		db.setGradientPaintTransformer(new StandardGradientPaintTransformer(GradientPaintTransformType.VERTICAL));
		plot.setBackground(db);
        DialTextAnnotation annotation1 = new DialTextAnnotation("Speed  Optimal");
		annotation1.setFont(new Font("Dialog", Font.BOLD, 12));
		annotation1.setRadius(0.7);
		plot.addLayer(annotation1);
		
		DialValueIndicator dvi = new DialValueIndicator(0);
		dvi.setFont(new Font("Dialog", 0, 10));
		dvi.setOutlinePaint(Color.darkGray);
		dvi.setRadius(0.59999999999999998D);
		dvi.setAngle(-103D);
		plot.addLayer(dvi);
		
		DialValueIndicator dvi1 = new DialValueIndicator(1);
		dvi1.setFont(new Font("Dialog", 0, 10));
		dvi1.setOutlinePaint(Color.red);
		dvi1.setRadius(0.59999999999999998D);
		dvi1.setAngle(-77D);
		plot.addLayer(dvi1);
 

		/* set the dial range and the angle of the inside circle for e.g 0 through 120 is the range of the values
		and the -120 is the starting angle and -300 is the ending angle in degrees.*/

		StandardDialScale scale = new StandardDialScale(0, 140, -140, -270,10,1);
		scale.setTickRadius(0.88);
		scale.setTickLabelOffset(0.15);
		scale.setTickLabelFont(new Font("Dialog", Font.PLAIN, 14));
		plot.addScale(0, scale);
		StandardDialRange range = new StandardDialRange(0.0, 50.0, Color.green);
		range.setInnerRadius(0.52);
		range.setOuterRadius(0.58);
		plot.addLayer(range);
		StandardDialRange range2 = new StandardDialRange(50.0, 90.0, Color.blue);
		range2.setInnerRadius(0.52);
		range2.setOuterRadius(0.58);
		plot.addLayer(range2);
		StandardDialRange range3 = new StandardDialRange(90.0, 140.0, Color.red);
		range3.setInnerRadius(0.52);
		range3.setOuterRadius(0.58);
		plot.addLayer(range3);
		
		DialPointer needle = new DialPointer.Pointer(0);
		plot.addLayer(needle);
		
		DialPointer pin = new DialPointer.Pin(1);
		pin.setRadius(0.55000000000000004D);
		plot.addPointer(pin);
		
		DialCap cap = new DialCap();
		cap.setRadius(0.1);
		plot.setCap(cap);

		float h = 500;//displayFrame.getHeight();

		//float w = 500;//displayFrame.getWidth();

        //GradientPaint gradientPaint = new GradientPaint(0.0F, 10.0F, Color.WHITE, h, w, Color.green.darker());

        //plot.setBackgroundPaint(gradientPaint);
					
		chart = new JFreeChart(plot);
		Image img = null;
		try {
			img = ImageIO.read(new File("backgrounds/speedchart/speedchart.jpg"));
		} catch (IOException e) {
		}
		
        chart.setBackgroundImage(img);
        
        panel = new ChartPanel(chart);
	}
	
	@Override
	public void addToBuffer(int index, double value) {
		buffer[index].setValue(value);

	}

	/**Register the given log so that it can monitor incoming data */
	public GUIDisplay registerLog(LogPanel log){
		this.log = log;
		logReg = true;
		return this;
	}
	
	@Override
	public Container getChart() {
		return panel;
	}

	@Override
	/**Return the buffer for the chart */
	public TelemetryDataEntry [] getBuffers() {
		
		dataEntries = new TelemetryDataEntry [2];
		for(int i = 0; i < dataEntries.length; i++)
			dataEntries[i] = new TelemetryDataEntry(1);
			
		/**Create the event(update chart) when this buffer receives
		 * new data */
		dataEntries[0].addTelemetryChartEventListener(
				new TelemetryChartListener() {
			public void myEventOccurred(TelemetryChartEvent evt) {
			/**	addToBuffer(0, dataEntries[0].getUpdate());*/
			}
		});

		dataEntries[1].addTelemetryChartEventListener(
				new TelemetryChartListener() {
			public void myEventOccurred(TelemetryChartEvent evt) {
				addToBuffer(1, dataEntries[1].getUpdate()[0]);
			}
		});
		
		/**TODO: send data to the log*/
		
		return dataEntries;
	}
}
